package com.sdy.healthcode.web.controller;

import com.sdy.common.model.BizException;
import com.sdy.common.model.Response;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.DateUtil;
import com.sdy.common.utils.MapUtil;
import com.sdy.healthcode.biz.constants.RedisConstants;
import com.sdy.healthcode.biz.dto.DepartmentDTO;
import com.sdy.healthcode.biz.dto.schedule.ScheduleSettings;
import com.sdy.healthcode.biz.model.ExpertsScheduleDaily;
import com.sdy.healthcode.biz.service.ExpertsScheduleDailyService;
import com.sdy.healthcode.biz.service.HsDepartmentService;
import com.sdy.mvc.controller.BaseController;
import com.sdy.redis.service.RedisService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/expertsSchedule")
@Api(tags = "医生排班")
public class ExpertsScheduleController extends BaseController {
    @Autowired
    private ExpertsScheduleDailyService expertsScheduleDailyService;
    @Autowired
    private HsDepartmentService hsDepartmentService;
    @Autowired
    private RedisLockRegistry redisLockRegistry;
    @Autowired
    private RedisService redisService;
    
    @GetMapping("/getData")
    @ApiOperation("科室排班数据")
    @ApiImplicitParam(value = "科室", name = "dept")
    public Response<ScheduleSettings> getData(Integer dept) throws BizException {
        return Response.success(expertsScheduleDailyService.getScheduleSettings(dept));
    }

    @PostMapping("/saveData")
    @ApiOperation("保存科室排班数据")
    public Response<String> saveData(@RequestBody ScheduleSettings scheduleSettings) throws BizException, InterruptedException {
        Assert.isNull(scheduleSettings.getDept(), "部门不能为空。");
        Lock lock = redisLockRegistry.obtain(RedisConstants.LOCK_SCHEDULE_SETTING_SAVE);
        if (!lock.tryLock(10, TimeUnit.SECONDS)) {
            return Response.error("服务器繁忙，请稍后再试。");
        }
        Date effectDate;
        try {
            expertsScheduleDailyService.saveScheduleSettings(scheduleSettings);
            // 计算生效日期
            Date today = DateUtil.getDateBegin(new Date());
            Date date = redisService.get(RedisConstants.SCHEDULED_DATE, Date.class);
            if (date != null) {
                effectDate = DateUtil.addDate(date, 1);
            } else {
                effectDate = DateUtil.addDate(today, 9);
            }
        } finally {
            lock.unlock();
        }
        return Response.success(DateUtil.formatDate(effectDate));
    }

    @GetMapping("/departmentInfo")
    @ApiOperation(value = "科室数据")
    public Response<List<DepartmentDTO>> departmentInfo() {
        List<DepartmentDTO> rootList = new ArrayList<>();
        List<DepartmentDTO> listData = hsDepartmentService.list()
                .stream()
                .map(d -> new DepartmentDTO()
                        .setName(d.getName())
                        .setParent(null)
                        .setValue(d.getId()))
                .collect(Collectors.toList());
        Map<Integer, DepartmentDTO> m = MapUtil.collectionToMap(listData, DepartmentDTO::getValue);
        for (DepartmentDTO department : listData) {
            DepartmentDTO parent = m.get(department.getParent());
            if (parent != null) {
                if (parent.getChildren() == null) {
                    parent.setChildren(new ArrayList<>());
                }
                parent.getChildren().add(department);
            } else {
                rootList.add(department);
            }
        }
        return Response.success(rootList);
    }
}
